package com.titanrise.crm.common.utils;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.titanrise.crm.common.enums.LogEffect;
import com.titanrise.crm.exception.InputFormatException;

import java.util.Scanner;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @Description:
 * @Author: pront
 * @Time:2024-11-08 10:01
 */
public class IOUtil {

    private static final Scanner sc = new Scanner(System.in);

    private static final Integer MAX_RECYCLE_COUNT = 10000 * 100; // 100W

    private static Thread waitThread = null;

    public static String inputLine() {
        return sc.nextLine();
    }

    public static final Function<String, Either<String, String>> checker = getGenericChecker();

    public static <T> T loading(Pair<Function<Integer, String>, LogEffect[]> onLoading, Pair<String, LogEffect[]> onFinished, Supplier<T> supplier) {
        Thread thread = new Thread(() -> {
            try {
                for (int i = 0; i < MAX_RECYCLE_COUNT; i++) {
                    String message = onLoading.getFirst().apply(i);
                    if (message != null) Console.print(i % 6 == 0 ? "\r" + message : ".", onLoading.getSecond());
                    Thread.sleep(250);
                }
                throw new RuntimeException("Loading Time Out!");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        thread.start();
        T res;
        try {
            res = supplier.get();
        } catch (Exception e) {
            Console.print("\r");
            throw e;
        } finally {
            thread.interrupt();
        }
        if (onFinished != null && onFinished.getFirst() != null && onFinished.getSecond() != null)
            Console.print("\r" + onFinished.getFirst(), onFinished.getSecond());
        return res;
    }

    public static Function<String, Either<String, String>> getGenericChecker(){
         return Functions.flow(
                ValidationUtil::trimThenRight,
                ValidationUtil.nonNull("输入不可为空！请重试！")
        );
    }

    public synchronized static Thread waitForSelective(String status) {
        Thread waitThreadRes = new Thread(() -> {
            System.out.print("请稍等，正在" + status + "中");
            int dotCount = 0;
            for (int i = 0; i < MAX_RECYCLE_COUNT; i++) {
                try {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println();
                        Console.println(status + "成功!", LogEffect.GREEN, LogEffect.ITALIC);
                        return;
                    }
                    Thread.sleep(300);
                    // 当打印6个点时，回到行首并清除
                    if (dotCount == 6) {
                        System.out.print("\r请稍等，正在" + status + "中"); // 回车到行首，重置点数
                        dotCount = 0;
                    }

                    System.out.print(".");
                    dotCount++;
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        if (ObjectUtil.isNotNull(waitThreadRes)) {
            waitThread = waitThreadRes;
        }
        waitThreadRes.start();
        return waitThreadRes;
    }

    public static int getIntegerNo(String content) throws InputFormatException {
        String noStr = ProjectUtil.getLine(content, checker);
        if(!NumberUtil.isInteger(noStr)) throw new InputFormatException("输入格式异常，请重新输入");
        return Integer.parseInt(noStr);
    }

    public void stopForSelective() {
        if (waitThread != null) waitThread.interrupt();
    }

    public static void main(String[] args) throws InterruptedException {
        Thread waitThread = waitForSelective("更新");
        Thread.sleep(5000);
        waitThread.interrupt();

    }

}
